package com.runa.rccprotocol.analysis.debao;

import com.alibaba.fastjson.JSON;
import com.runa.monitor.comm.dto.Meter;
import com.runa.monitor.comm.dto.Node;
import com.runa.monitor.comm.dto.newComm.HotMeterVO;
import com.runa.monitor.comm.entity.CommMeter;
import com.runa.persistence.StringUtil;
import com.runa.persistence.service.LogService;
import com.runa.persistence.task.RequestPendingTask;
import com.runa.persistence.task.TaskTypeEnum;
import com.runa.persistence.util.LogUtil;
import com.runa.protocol.analysis.ShellBufferAnalysis;
import com.runa.protocol.dto.DtuReport;
import com.runa.protocol.dto.IInterData;
import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.util.ByteUtil;
import com.runa.rccprotocol.dto.debao.*;
import com.runa.rccprotocol.dto.runa.RunaConcenResponseData;
import com.runa.rccprotocol.dto.runa.RunaFrameSequence;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
public class DeBao2Analysis extends ShellBufferAnalysis<byte[]> {


    public DeBao2Analysis() {
        super(null, 0);
    }

    public void saveLog(String identify, String event, byte[] data, int length) {
        if (log.isDebugEnabled()) {
            LogService.saveErrorLog(identify, event, data, length);
        }
    }

    @Override
    public int fill(byte[] data, int size,String n) {
        if (StringUtil.isBlank(n)) {
            LogUtil.getLogAndInfo("未知", "德宝", "{}", ByteUtil.byteToHexString(data, 0, size));
        }
        log.debug("德宝: {} {}", n, ByteUtil.byteToHexString(data, 0, size));
        if (size < 6) {
            saveLog("德宝", "长度小于6", data, size);
            LogUtil.getLogAndInfo("未知", "德宝", "{} 长度小于6: {}", n, ByteUtil.byteToHexString(data, 0, size));
            return -1;
        }
        int begin;
        for (begin = 0;begin < size;begin++) {
            if ((data[begin]&0xff) == 0x68
                    && data[begin+5] == 0x68) {
                break;
            }
        }
        int L = (((data[begin+1]&0xff)) + (data[begin+2]<<8)) >> 2;
        if (size < L + 8) {
            saveLog("德宝", "长度问题", data, size);
            LogUtil.getLogAndInfo("未知", "德宝", "{} 长度问题: {}", n, ByteUtil.byteToHexString(data, 0, size));
            return -1;
        }
        if ((data[begin+6+L] != ByteUtil.sum(data, begin+6, L))){
            saveLog("德宝", "校验失败", data, size);
            LogUtil.getLogAndInfo("未知", "德宝", "{} 校验失败: {}", n, ByteUtil.byteToHexString(data, 0, size));
            return -1;
        }
        int type = data[begin + 6] & 0xff;
        switch (type) {
            case 0xC4:
                saveLog("德宝", "主动上报抄表时间", data, size);
                no(data);
                if (data[12] == 0x0E) {
                    if (data[22] == 0x28 && data[23] == 0x0B && data[24] == 0x01) {
                        byte[] readTime = ByteUtil.slice(data, 25, 5);
                        DeBaoInfoCache.put(netEquNo, new DeBaoInfo(readTime, data[11]));
                        log.info("自动上报: {} {} {}", netEquNo, ByteUtil.byteToHexString(readTime), JSON.toJSONString(DeBaoInfoCache.getMap()));
                    }
                }
                break;
            //注册包或者心跳包
            case 0xC9:
                no(data);
                byte afn = data[12];
                int pn = RunaFrameSequence.pn(data[14], data[15]);
                int fn = RunaFrameSequence.fn(data[16], data[17]);
                DtuReport dtuReport = new DtuReport(netEquNo);
                dtuReport.setMustAck(true);
                if (afn == 0x02 && pn == 0 && fn == 1) {
                    LogUtil.linkDetect(netEquNo, "德宝", data, size, "登录");
                    DeBaoReportAck deBaoReportAck = new DeBaoReportAck(data);
                    dtuReport.setAck(deBaoReportAck);
                    this.interData = dtuReport;
                    saveLog("德宝", "登录", data, size);
                } else if (afn == 0x02 && pn == 0 && fn == 2) {
                    LogUtil.linkDetect(netEquNo, "德宝", data, size, "退出登录");
                    saveLog("德宝", "退出登录", data, size);
                } else if (afn == 0x02 && pn == 0 && fn == 3) {
                    LogUtil.linkDetect(netEquNo, "德宝", data, size, "心跳");
                    DeBaoReportAck deBaoReportAck = new DeBaoReportAck(data);
                    dtuReport.setAck(deBaoReportAck);
                    this.interData = dtuReport;
                    saveLog("德宝", "心跳", data, size);
                }
                break;
            case 0x88:
                no(data);
                HotMeterVO meterData = new HotMeterVO();
                if (data[12] == 0x0C && data[14] == 0x00 && data[15] == 0x00 && data[16] == 0x04 && data[17] == 0x16) {
                    byte[] readTime = ByteUtil.slice(data, 18, 5);
                    DeBaoInfoCache.put(netEquNo, new DeBaoInfo(readTime, data[11]));
                    log.debug("DeBaoInfoCache: {} {} {} {}", netEquNo, ByteUtil.byteToHexString(readTime), JSON.toJSONString(DeBaoInfoCache.getMap()), DeBaoInfoCache.getMap().size());
                    saveLog("德宝", "响应请求抄表时间", data, size);
                } else if (data[12] == 0x0C && data[16] == 0x02 && data[17] == 0x16) {
                    handleMeterDataByIndex(data, begin, meterData);
                } else if (data[12] == 0x0D && data[16] == 0x40 && data[17] == 0x1B) {
                    DeBaoAnalysisData deBaoAnalysisData = new DeBaoAnalysisData(netEquNo);
                    deBaoAnalysisData.analysisAutoRead(data);
                    DeBaoResponseData deBaoResponseData = new DeBaoResponseData();
                    deBaoResponseData.addRepData(deBaoAnalysisData);
                    interData = deBaoResponseData;
                }

            default:
        }
        return 0;
    }

    private void no(byte[] data) {
        String a1= ByteUtil.bcd2str(data, 7, 2, false);
        short a2=ByteUtil.byteToShort(data, 7 + 2, ByteOrder.BA);
        netEquNo = String.format("%05d", a2)+a1;
    }


    private void handleMeterDataByIndex(byte[] data, int index, HotMeterVO meterData) {
        index += 14;
        int pn = RunaFrameSequence.pn(data[index++], data[index++]);
        int fn = RunaFrameSequence.fn(data[index++], data[index++]);
        meterData.setIndexNo(pn);
        index += 5;
        handleMeterData(data, index, meterData);
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        responseData.setAddress(netEquNo);
        responseData.addRepData(meterData);
        interData = responseData;
    }


    private void handleMeterData(byte[] data, int index, HotMeterVO meterData) {
        //结算日热量
        double theCurrentHeat = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        index+=4;
        //当前热量(总热量).
        ++index;
        double theCurrentHeatSum = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        RequestPendingTask task = RequestPendingTask.getTask(netEquNo);
        if (null != task && null != task.getNode()) {
            Node node = task.getNode();
            String model = node.getModel();
            if ("HM-25-U/200".equalsIgnoreCase(model)) {
                theCurrentHeatSum = ByteUtil.byteToUInt(data, index, ByteOrder.DCBA);
            }
        }
        meterData.setAccHeat((float) theCurrentHeatSum);
        index+=4;
        //热功率
        ++index;
        double thermalPower = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        meterData.setPower( (float) thermalPower);
        index+=4;
        //瞬时流量
        ++index;
        double instantaneousDelivery = ByteUtil.bcdToInt(data, index, 4, false) * 0.0001;
        meterData.setFlow( (float) instantaneousDelivery);
        index+=4;
        //累计流量
        ++index;
        double cumulativeDischarge = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        meterData.setAccFlow( (float) cumulativeDischarge);
        index+=5;
        //进水温
        double intoTheWater = ByteUtil.bcdToInt(data, index, 3, false) * 0.01;
        meterData.setSupplyTemp( (float) intoTheWater);
        index+=3;
        //回水温度
        double returnWaterTemperature = ByteUtil.bcdToInt(data, index, 3, false) * 0.01;
        meterData.setReturnTemp( (float) returnWaterTemperature);
        index+=3;

        //无单位,累计工作时间
        int openTime = ByteUtil.bcdToInt(data, index, 3, false);
        meterData.setWorkTime(openTime);
        index+=3;
        try {
            meterData.setMeterDate((new SimpleDateFormat("yyyyMMddHHmmss").parse(ByteUtil.bcd2str(data, index, 7, false))));
        } catch (ParseException ignored) {

        }
        meterData.setReadDate(new Date());
    }


    public static void main(String[] args) {
        CommMeter commMeter = CommMeter.builder().model("HM-25-U/200").build();
        Meter meter = Meter.getMeter(commMeter);
        RequestPendingTask.addTask("103611361", new RequestPendingTask(TaskTypeEnum.READ_METER, meter));
        DeBao2Analysis analysis =  new DeBao2Analysis();
        String s = "68 32 00 32 00 68 C9 34 11 96 27 00 02 74 00 00 04 00 45 16";
        byte[] bytes = ByteUtil.hexStringToByte(s);
        analysis.fill(bytes, bytes.length, "103611361");
        IInterData gain = analysis.gain();
        System.out.println(JSON.toJSONString(gain));
    }

}
